package com.hmall.gateway.filters;

import cn.hutool.core.util.StrUtil;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.util.JwtTool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 自定义身份过滤器
 *
 * @author Zhy
 * @version 1.0
 * @date 2025-03-18 11:28
 */
@Slf4j
@Component
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class AutoGlobalFilter implements GlobalFilter, Ordered {

	private final AuthProperties authProperties;
	private final JwtTool jwtTool;

	private final AntPathMatcher antPathMatcher = new AntPathMatcher();

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
		ServerHttpResponse response = exchange.getResponse();

		// 1. 获取请求路径
		String path = request.getPath().toString();

		// 2. 获取白名单
		List<String> excludePaths = authProperties.getExcludePaths();

		// 3. 判断是否在白名单中
		long count = excludePaths.stream().filter(item -> antPathMatcher.match(item, path)).count();
		if (count > 0) {
			// 4. 请求路径在白名单中，放行
			return chain.filter(exchange);
		}

		// 5. 校验token
		String token = exchange.getRequest().getHeaders().getFirst("authorization");
		if (StrUtil.isBlank(token)) {
			// 拒接访问，返回 401
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			return response.setComplete();
		}

		// 6. 解析 token
		Long userId = null;
		try {
			userId = jwtTool.parseToken(token);
		} catch (Exception e) {
			// 拒接访问，返回 401
			response.setStatusCode(HttpStatus.UNAUTHORIZED);
			return response.setComplete();
		}

		// 向下传递 userId
		request.mutate().header("user-info", Long.toString(userId));

		// 7. 放行
		// log.info("userId: {}", userId);
		return chain.filter(exchange);
	}

	@Override
	public int getOrder() {
		return 0;
	}

}
